#include <stdio.h>
#include "token.h"

#define KEY_SET    \
  "_-.:,;<>abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@0123456789=/\\'\"{}[]"

#define SPLIT_SET " "


static const char *token_expect(char c)
{
	if (strchr(SPLIT_SET, c) != NULL) {
		return SPLIT_SET;
	}
	if (strchr(KEY_SET, c) != NULL) {
		return KEY_SET;
	}
	return "";
}

static seg_t token_fetch(const char *buf, int buf_size, seg_t cur)
{
	seg_point_t start = end_seg(cur);
	const char *expect = token_expect(buf[start]);
	seg_point_t end;
	for (end = start; end < buf_size; end++) {
		if (strchr(expect, buf[end]) == NULL)
			break;
	}
	return make_seg(start, end);
}

static int token_white(const char *buf, seg_t s)
{
  seg_point_t i;
  for (i = start_seg(s); i < end_seg(s); i++){
    if (buf[i] != ' ')
      return 0;
  }
  return 1;
}

int token_push(struct token *token, seg_t s)
{
  return seg_list_push(&token->segs, s);
}

seg_t token_pop(struct token *token)
{
  return seg_list_pop(&token->segs);
}

seg_t token_pop_front(struct token *token)
{
  return seg_list_pop_front(&token->segs);
}

seg_t token_front(struct token *token)
{
  return seg_list_front(&token->segs);
}

seg_t token_back(struct token *token)
{
  return seg_list_back(&token->segs);
}

int token_size(struct token *token)
{
  return seg_list_size(&token->segs);
}

void token_init(struct token *token)
{
  seg_list_init(&token->segs);
  token->last_white = 0;
}

int tokenize(struct token *token, const char *buf, int size)
{
  token_init(token);
	seg_t s = make_seg(NONE_SEG, NONE_SEG);
	do {
		s = token_fetch(buf, size, s);
		if (!valid_seg(s)) 
			break;
    token->last_white =  token_white(buf, s);
		if (!token->last_white && token_push(token, s) < 0) 
			return -1;
	} while (1);
	return 0;
}

int token_show(seg_t seg, const void *userdata)
{
  const char *buf = (const char *)userdata;
  seg_point_t end = end_seg(seg);
	seg_point_t start = start_seg(seg);
  for (;start < end; start++){
		printf ("%c",  buf[start]);
	}
  printf (" ");
  return 0;
}

int token_print(struct token *token, const char *buf)
{
  foreach_seg(&token->segs, token_show, buf);
	printf ("#\n");
  fflush(stdout);
	return 0;
}


